package com.kanche.bigbaby.support.smlistview;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.kanche.bigbaby.R;

/**
 * 
 * @author baoyz
 * @date 2014-8-18
 * 
 */
public class SwipeMenuListView extends ListView implements AbsListView.OnScrollListener{

	Context context;

	private static final int TOUCH_STATE_NONE = 0;
	private static final int TOUCH_STATE_X = 1;
	private static final int TOUCH_STATE_Y = 2;

	private int MAX_Y = 5;
	private int MAX_X = 3;
	private float mDownX;
	private float mDownY;
	private int mTouchState;
	private int mTouchPosition;
	private SwipeMenuLayout mTouchView;
	private OnSwipeListener mOnSwipeListener;
	OnLoadMoreListener mOnLoadMoreListener;

	public OnLoadMoreListener getmOnLoadMoreListener() {
		return mOnLoadMoreListener;
	}

	public void setmOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
		this.mOnLoadMoreListener = mOnLoadMoreListener;
	}

	private SwipeMenuCreator mMenuCreator;
	private OnMenuItemClickListener mOnMenuItemClickListener;
	private Interpolator mCloseInterpolator;
	private Interpolator mOpenInterpolator;

	public SwipeMenuListView(Context context) {
		this(context, null);
	}

	public SwipeMenuListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		getAttrs(context, attrs);
		this.context = context;
		init();
	}

	public SwipeMenuListView(Context context, AttributeSet attrs) {
		super(context, attrs);

		getAttrs(context, attrs);
		this.context = context;
		init();
	}

	private void init() {
		MAX_X = dp2px(MAX_X);
		MAX_Y = dp2px(MAX_Y);
		mTouchState = TOUCH_STATE_NONE;
		setOnScrollListener(this);


		initDropDownStyle();
	}


	@Override
	public void setAdapter(ListAdapter adapter) {
		super.setAdapter(new SwipeMenuAdapter(getContext(), adapter) {
			@Override
			public void createMenu(SwipeMenu menu) {
				if (mMenuCreator != null) {
					mMenuCreator.create(menu);
				}
			}

			@Override
			public void onItemClick(SwipeMenuView view, SwipeMenu menu,
									int index) {
				boolean flag = false;
				if (mOnMenuItemClickListener != null) {
					flag = mOnMenuItemClickListener.onMenuItemClick(
							view.getPosition(), menu, index);
				}
				if (mTouchView != null && !flag) {
					mTouchView.smoothCloseMenu();
				}
			}
		});
	}

	public void setCloseInterpolator(Interpolator interpolator) {
		mCloseInterpolator = interpolator;
	}

	public void setOpenInterpolator(Interpolator interpolator) {
		mOpenInterpolator = interpolator;
	}

	public Interpolator getOpenInterpolator() {
		return mOpenInterpolator;
	}

	public Interpolator getCloseInterpolator() {
		return mCloseInterpolator;
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		return super.onInterceptTouchEvent(ev);
	}

	int lastVisibleItem = -1;
	View foot = null;
	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {

//		if(scrollState == OnScrollListener.SCROLL_STATE_IDLE && lastVisibleItem == getAdapter().getCount()){
		if(lastVisibleItem == getAdapter().getCount() && getFooterViewsCount() == 0 &&getAdapter().getCount()>0){

			foot = LayoutInflater.from(context).inflate(R.layout.footerview,null);

			addFooterView(foot);
			mOnLoadMoreListener.loadMore();
		}

		if (isDropDownStyle) {
			currentScrollState = scrollState;

			if (currentScrollState == SCROLL_STATE_IDLE) {
				hasReachedTop = false;
			}
		}

	}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

		lastVisibleItem = firstVisibleItem + visibleItemCount ;

		if (isDropDownStyle) {
			if (currentScrollState == SCROLL_STATE_TOUCH_SCROLL && currentHeaderStatus != HEADER_STATUS_LOADING) {
				/**
				 * when state of ListView is SCROLL_STATE_TOUCH_SCROLL(ListView is scrolling and finger is on screen)
				 * and header status is not HEADER_STATUS_LOADING
				 * <ul>
				 * if header layout is visiable,
				 * <li>if height of header is higher than a fixed value, then set header status to
				 * HEADER_STATUS_RELEASE_TO_LOAD.</li>
				 * <li>else set header status to HEADER_STATUS_DROP_DOWN_TO_LOAD.</li>
				 * </ul>
				 * <ul>
				 * if header layout is not visiable,
				 * <li>set header status to HEADER_STATUS_CLICK_TO_LOAD.</li>
				 * </ul>
				 */
				if (firstVisibleItem == 0) {
					headerImage.setVisibility(View.VISIBLE);
					int pointBottom = headerOriginalHeight + headerReleaseMinDistance;
					if (headerLayout.getBottom() >= pointBottom) {
						setHeaderStatusReleaseToLoad();
					} else if (headerLayout.getBottom() < pointBottom) {
						setHeaderStatusDropDownToLoad();
					}
				} else {
					setHeaderStatusClickToLoad();
				}
			} else if (currentScrollState == SCROLL_STATE_FLING && firstVisibleItem == 0
					&& currentHeaderStatus != HEADER_STATUS_LOADING) {
				/**
				 * when state of ListView is SCROLL_STATE_FLING(ListView is scrolling but finger has leave screen) and
				 * first item(header layout) is visible and header status is not HEADER_STATUS_LOADING, then hide first
				 * item, set second item visible and set hasReachedTop true.
				 */
				setSecondPositionVisible();
				hasReachedTop = true;
			} else if (currentScrollState == SCROLL_STATE_FLING && hasReachedTop) {
				/**
				 * when state of ListView is SCROLL_STATE_FLING(ListView is scrolling but finger has leave screen) and
				 * hasReachedTop is true(it's because flick back), then hide first item, set second item visible.
				 */
				setSecondPositionVisible();
			}
		}
		
		
	}

	/**
	 * no more or failed
	 */
	public void stopLoadMore(){
		if(null != foot ){
			removeFooterView(foot);
		}
	}
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if (ev.getAction() != MotionEvent.ACTION_DOWN && mTouchView == null)
			return super.onTouchEvent(ev);
		int action = MotionEventCompat.getActionMasked(ev);
		action = ev.getAction();


		hasReachedTop = false;
		
		switch (action) {
		case MotionEvent.ACTION_DOWN:

			actionDownPointY = ev.getY();
			
			int oldPos = mTouchPosition;
			mDownX = ev.getX();
			mDownY = ev.getY();
			mTouchState = TOUCH_STATE_NONE;

			mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());

			if (mTouchPosition == oldPos && mTouchView != null
					&& mTouchView.isOpen()) {
				mTouchState = TOUCH_STATE_X;
				mTouchView.onSwipe(ev);
				return true;
			}

			View view = getChildAt(mTouchPosition - getFirstVisiblePosition());

			if (mTouchView != null && mTouchView.isOpen()) {
				mTouchView.smoothCloseMenu();
				mTouchView = null;
				// return super.onTouchEvent(ev);
				// try to cancel the touch event
				MotionEvent cancelEvent = MotionEvent.obtain(ev);  
				cancelEvent.setAction(MotionEvent.ACTION_CANCEL);    
				onTouchEvent(cancelEvent);
				return true;
			}
			if (view instanceof SwipeMenuLayout) {
				mTouchView = (SwipeMenuLayout) view;
			}
			if (mTouchView != null) {
				mTouchView.onSwipe(ev);
			}
			break;
		case MotionEvent.ACTION_MOVE:

			adjustHeaderPadding(ev);
			
			float dy = Math.abs((ev.getY() - mDownY));
			float dx = Math.abs((ev.getX() - mDownX));
			if (mTouchState == TOUCH_STATE_X) {
				if (mTouchView != null) {
					mTouchView.onSwipe(ev);
				}
				getSelector().setState(new int[] { 0 });
				ev.setAction(MotionEvent.ACTION_CANCEL);
				super.onTouchEvent(ev);
				return true;
			} else if (mTouchState == TOUCH_STATE_NONE) {
				if (Math.abs(dy) > MAX_Y) {
					mTouchState = TOUCH_STATE_Y;
				} else if (dx > MAX_X) {
					mTouchState = TOUCH_STATE_X;
					if (mOnSwipeListener != null) {
						mOnSwipeListener.onSwipeStart(mTouchPosition);
					}
				}
			}
			break;
		case MotionEvent.ACTION_UP:

			if (!isVerticalScrollBarEnabled()) {
				setVerticalScrollBarEnabled(true);
			}
			/**
			 * set status when finger leave screen if first item visible and header status is not
			 * HEADER_STATUS_LOADING
			 * <ul>
			 * <li>if current header status is HEADER_STATUS_RELEASE_TO_LOAD, call onDropDown.</li>
			 * <li>if current header status is HEADER_STATUS_DROP_DOWN_TO_LOAD, then set header status to
			 * HEADER_STATUS_CLICK_TO_LOAD and hide header layout.</li>
			 * </ul>
			 */
			if (getFirstVisiblePosition() == 0 && currentHeaderStatus != HEADER_STATUS_LOADING) {
				switch (currentHeaderStatus) {
					case HEADER_STATUS_RELEASE_TO_LOAD:
						onDropDown();
						break;
					case HEADER_STATUS_DROP_DOWN_TO_LOAD:
						setHeaderStatusClickToLoad();
						setSecondPositionVisible();
						break;
					case HEADER_STATUS_CLICK_TO_LOAD:
					default:
						break;
				}
			}
			
			
			if (mTouchState == TOUCH_STATE_X) {
				if (mTouchView != null) {
					mTouchView.onSwipe(ev);
					if (!mTouchView.isOpen()) {
						mTouchPosition = -1;
						mTouchView = null;
					}
				}
				if (mOnSwipeListener != null) {
					mOnSwipeListener.onSwipeEnd(mTouchPosition);
				}
				ev.setAction(MotionEvent.ACTION_CANCEL);
				super.onTouchEvent(ev);
				return true;
			}
			break;
		}
		return super.onTouchEvent(ev);
	}

	public void smoothOpenMenu(int position) {
		if (position >= getFirstVisiblePosition()
				&& position <= getLastVisiblePosition()) {
			View view = getChildAt(position - getFirstVisiblePosition());
			if (view instanceof SwipeMenuLayout) {
				mTouchPosition = position;
				if (mTouchView != null && mTouchView.isOpen()) {
					mTouchView.smoothCloseMenu();
				}
				mTouchView = (SwipeMenuLayout) view;
				mTouchView.smoothOpenMenu();
			}
		}
	}

	private int dp2px(int dp) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
				getContext().getResources().getDisplayMetrics());
	}

	public void setMenuCreator(SwipeMenuCreator menuCreator) {
		this.mMenuCreator = menuCreator;
	}

	public void setOnMenuItemClickListener(
			OnMenuItemClickListener onMenuItemClickListener) {
		this.mOnMenuItemClickListener = onMenuItemClickListener;
	}

	public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
		this.mOnSwipeListener = onSwipeListener;
	}


	public static interface OnMenuItemClickListener {
		boolean onMenuItemClick(int position, SwipeMenu menu, int index);
	}

	public static interface OnSwipeListener {
		void onSwipeStart(int position);

		void onSwipeEnd(int position);
	}
	public static interface OnLoadMoreListener {
		void loadMore();

//		void onSwipeEnd(int position);
	}


	//============new: add head

	private boolean            isDropDownStyle         = true;
	private boolean            isOnBottomStyle         = true;
	private boolean            isAutoLoadOnBottom      = false;

	private String             headerDefaultText;
	private String             headerPullText;
	private String             headerReleaseText;
	private String             headerLoadingText;
	private String             footerDefaultText;
	private String             footerLoadingText;
	private String             footerNoMoreText;

	/** header layout view **/
	private RelativeLayout headerLayout;
	private ImageView headerImage;
	private ProgressBar headerProgressBar;
	private TextView headerText;
	private TextView           headerSecondText;


	private OnDropDownListener onDropDownListener;
	private OnScrollListener   onScrollListener;

	/** rate about drop down distance and header padding top when drop down **/
	private float              headerPaddingTopRate    = 1.5f;
	/** min distance which header can release to loading **/
	private int                headerReleaseMinDistance;

	/** whether bottom listener has more **/
	private boolean            hasMore                 = true;
	/** whether show footer loading progress bar when loading **/
	private boolean            isShowFooterProgressBar = true;
	/** whether show footer when no more data **/
	private boolean            isShowFooterWhenNoMore  = false;

	private int                currentScrollState;
	private int                currentHeaderStatus;

	/** whether reached top, when has reached top, don't show header layout **/
	private boolean            hasReachedTop           = false;

	/** image flip animation **/
	private RotateAnimation    flipAnimation;
	/** image reverse flip animation **/
	private RotateAnimation    reverseFlipAnimation;

	/** header layout original height **/
	private int                headerOriginalHeight;
	/** header layout original padding top **/
	private int                headerOriginalTopPadding;
	/** y of point which user touch down **/
	private float              actionDownPointY;

	/** whether is on bottom loading **/
	private boolean            isOnBottomLoading       = false;


	/**
	 * init drop down style, only init once
	 */
	private void initDropDownStyle() {
		if (headerLayout != null) {
			if (isDropDownStyle) {
				addHeaderView(headerLayout);
			} else {
				removeHeaderView(headerLayout);
			}
			return;
		}
		if (!isDropDownStyle) {
			return;
		}

		headerReleaseMinDistance = context.getResources().getDimensionPixelSize(
				R.dimen.drop_down_list_header_release_min_distance);
		flipAnimation = new RotateAnimation(0, 180, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		flipAnimation.setInterpolator(new LinearInterpolator());
		flipAnimation.setDuration(250);
		flipAnimation.setFillAfter(true);
		reverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		reverseFlipAnimation.setInterpolator(new LinearInterpolator());
		reverseFlipAnimation.setDuration(250);
		reverseFlipAnimation.setFillAfter(true);

		headerDefaultText = context.getString(R.string.drop_down_list_header_default_text);
		headerPullText = context.getString(R.string.drop_down_list_header_pull_text);
		headerReleaseText = context.getString(R.string.drop_down_list_header_release_text);
		headerLoadingText = context.getString(R.string.drop_down_list_header_loading_text);

		LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		headerLayout = (RelativeLayout)inflater.inflate(R.layout.drop_down_list_header, this, false);
		headerText = (TextView)headerLayout.findViewById(R.id.drop_down_list_header_default_text);
		headerImage = (ImageView)headerLayout.findViewById(R.id.drop_down_list_header_image);
		headerProgressBar = (ProgressBar)headerLayout.findViewById(R.id.drop_down_list_header_progress_bar);
		headerSecondText = (TextView)headerLayout.findViewById(R.id.drop_down_list_header_second_text);
		headerLayout.setClickable(true);
		headerLayout.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				onDropDown();
			}
		});
		headerText.setText(headerDefaultText);
		addHeaderView(headerLayout);

		measureHeaderLayout(headerLayout);
		headerOriginalHeight = headerLayout.getMeasuredHeight();
		headerOriginalTopPadding = headerLayout.getPaddingTop();
		currentHeaderStatus = HEADER_STATUS_CLICK_TO_LOAD;
	}


	/**
	 * @return isDropDownStyle
	 */
	public boolean isDropDownStyle() {
		return isDropDownStyle;
	}

	/**
	 * @param isDropDownStyle
	 */
	public void setDropDownStyle(boolean isDropDownStyle) {
		if (this.isDropDownStyle != isDropDownStyle) {
			this.isDropDownStyle = isDropDownStyle;
			initDropDownStyle();
		}
	}
	/**
	 * @param onDropDownListener
	 */
	public void setOnDropDownListener(OnDropDownListener onDropDownListener) {
		this.onDropDownListener = onDropDownListener;
	}

	/**
	 * drop down begin, adjust view status
	 */
	private void onDropDownBegin() {
		if (isDropDownStyle) {
			setHeaderStatusLoading();
		}
	}

	/**
	 * on drop down loading, you can call it by manual, but you should manual call onBottomComplete at the same time.
	 */
	public void onDropDown() {
		if (currentHeaderStatus != HEADER_STATUS_LOADING && isDropDownStyle && onDropDownListener != null) {
			onDropDownBegin();
			onDropDownListener.onDropDown();
		}
	}

	/**
	 * drop down complete, restore view status
	 *
	 * @param secondText display below header text, if null, not display
	 */
	public void onDropDownComplete(CharSequence secondText) {
		if (isDropDownStyle) {
			setHeaderSecondText(secondText);
			onDropDownComplete();
		}
	}

	/**
	 * set header second text
	 *
	 * @param secondText secondText display below header text, if null, not display
	 */
	public void setHeaderSecondText(CharSequence secondText) {
		if (isDropDownStyle) {
			if (secondText == null) {
				headerSecondText.setVisibility(View.GONE);
			} else {
				headerSecondText.setVisibility(View.VISIBLE);
				headerSecondText.setText(secondText);
			}
		}
	}

	/**
	 * drop down complete, restore view status
	 */
	public void onDropDownComplete() {
		if (isDropDownStyle) {
			setHeaderStatusClickToLoad();

			if (headerLayout.getBottom() > 0) {
				invalidateViews();
				setSecondPositionVisible();
			}
		}
	}
	/**
	 * OnDropDownListener, called when header released
	 *
	 * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2012-5-31
	 */
	public interface OnDropDownListener {

		/**
		 * called when header released
		 */
		public void onDropDown();
	}
	/**
	 * set second position visible(index is 1), because first position is header layout
	 */
	public void setSecondPositionVisible() {
		if (getAdapter() != null && getAdapter().getCount() > 0 && getFirstVisiblePosition() == 0) {
			setSelection(1);
		}
	}

	/**
	 * get header layout view
	 *
	 * @return
	 */
	public RelativeLayout getHeaderLayout() {
		return headerLayout;
	}

	/**
	 * get rate about drop down distance and header padding top when drop down
	 *
	 * @return headerPaddingTopRate
	 */
	public float getHeaderPaddingTopRate() {
		return headerPaddingTopRate;
	}

	/**
	 * set rate about drop down distance and header padding top when drop down
	 *
	 * @param headerPaddingTopRate
	 */
	public void setHeaderPaddingTopRate(float headerPaddingTopRate) {
		this.headerPaddingTopRate = headerPaddingTopRate;
	}

	/**
	 * get min distance which header can release to loading
	 *
	 * @return headerReleaseMinDistance
	 */
	public int getHeaderReleaseMinDistance() {
		return headerReleaseMinDistance;
	}

	/**
	 * set min distance which header can release to loading
	 *
	 * @param headerReleaseMinDistance
	 */
	public void setHeaderReleaseMinDistance(int headerReleaseMinDistance) {
		this.headerReleaseMinDistance = headerReleaseMinDistance;
	}

	/***
	 * get header default text, default is R.string.drop_down_list_header_default_text
	 *
	 * @return
	 */
	public String getHeaderDefaultText() {
		return headerDefaultText;
	}

	/**
	 * set header default text, default is R.string.drop_down_list_header_default_text
	 *
	 * @param headerDefaultText
	 */
	public void setHeaderDefaultText(String headerDefaultText) {
		this.headerDefaultText = headerDefaultText;
		if (headerText != null && currentHeaderStatus == HEADER_STATUS_CLICK_TO_LOAD) {
			headerText.setText(headerDefaultText);
		}
	}

	/**
	 * get header pull text, default is R.string.drop_down_list_header_pull_text
	 *
	 * @return
	 */
	public String getHeaderPullText() {
		return headerPullText;
	}

	/**
	 * set header pull text, default is R.string.drop_down_list_header_pull_text
	 *
	 * @param headerPullText
	 */
	public void setHeaderPullText(String headerPullText) {
		this.headerPullText = headerPullText;
	}
	/**
	 * get header release text, default is R.string.drop_down_list_header_release_text
	 *
	 * @return
	 */
	public String getHeaderReleaseText() {
		return headerReleaseText;
	}

	/**
	 * set header release text, default is R.string.drop_down_list_header_release_text
	 *
	 * @param headerReleaseText
	 */
	public void setHeaderReleaseText(String headerReleaseText) {
		this.headerReleaseText = headerReleaseText;
	}

	/**
	 * get header loading text, default is R.string.drop_down_list_header_loading_text
	 *
	 * @return
	 */
	public String getHeaderLoadingText() {
		return headerLoadingText;
	}
	/**
	 * set header loading text, default is R.string.drop_down_list_header_loading_text
	 *
	 * @param headerLoadingText
	 */
	public void setHeaderLoadingText(String headerLoadingText) {
		this.headerLoadingText = headerLoadingText;
	}

	/** status which you can click to load, init satus **/
	public static final int HEADER_STATUS_CLICK_TO_LOAD     = 1;
	/**
	 * status which you can drop down and then release to excute onDropDownListener, when height of header layout lower
	 * than a value
	 **/
	public static final int HEADER_STATUS_DROP_DOWN_TO_LOAD = 2;
	/** status which you can release to excute onDropDownListener, when height of header layout higher than a value **/
	public static final int HEADER_STATUS_RELEASE_TO_LOAD   = 3;
	/** status which is loading **/
	public static final int HEADER_STATUS_LOADING           = 4;

	/**
	 * set header status to {@link #HEADER_STATUS_CLICK_TO_LOAD}
	 */
	private void setHeaderStatusClickToLoad() {
		if (currentHeaderStatus != HEADER_STATUS_CLICK_TO_LOAD) {
			resetHeaderPadding();

			headerImage.clearAnimation();
			headerImage.setVisibility(View.GONE);
			headerProgressBar.setVisibility(View.GONE);
			headerText.setText(headerDefaultText);

			currentHeaderStatus = HEADER_STATUS_CLICK_TO_LOAD;
		}
	}

	/**
	 * set header status to {@link #HEADER_STATUS_DROP_DOWN_TO_LOAD}
	 */
	private void setHeaderStatusDropDownToLoad() {
		if (currentHeaderStatus != HEADER_STATUS_DROP_DOWN_TO_LOAD) {
			headerImage.setVisibility(View.VISIBLE);
			if (currentHeaderStatus != HEADER_STATUS_CLICK_TO_LOAD) {
				headerImage.clearAnimation();
				headerImage.startAnimation(reverseFlipAnimation);
			}
			headerProgressBar.setVisibility(View.GONE);
			headerText.setText(headerPullText);

			if (isVerticalFadingEdgeEnabled()) {
				setVerticalScrollBarEnabled(false);
			}

			currentHeaderStatus = HEADER_STATUS_DROP_DOWN_TO_LOAD;
		}
	}

	/**
	 * set header status to {@link #HEADER_STATUS_RELEASE_TO_LOAD}
	 */
	private void setHeaderStatusReleaseToLoad() {
		if (currentHeaderStatus != HEADER_STATUS_RELEASE_TO_LOAD) {
			headerImage.setVisibility(View.VISIBLE);
			headerImage.clearAnimation();
			headerImage.startAnimation(flipAnimation);
			headerProgressBar.setVisibility(View.GONE);
			headerText.setText(headerReleaseText);

			currentHeaderStatus = HEADER_STATUS_RELEASE_TO_LOAD;
		}
	}

	/**
	 * set header status to {@link #HEADER_STATUS_LOADING}
	 */
	private void setHeaderStatusLoading() {
		if (currentHeaderStatus != HEADER_STATUS_LOADING) {
			resetHeaderPadding();

			headerImage.setVisibility(View.GONE);
			headerImage.clearAnimation();
			headerProgressBar.setVisibility(View.VISIBLE);
			headerText.setText(headerLoadingText);

			currentHeaderStatus = HEADER_STATUS_LOADING;
			setSelection(0);
		}
	}

	/**
	 * adjust header padding according to motion event
	 *
	 * @param ev
	 */
	private void adjustHeaderPadding(MotionEvent ev) {
		// adjust header padding according to motion event history
		int pointerCount = ev.getHistorySize();
		if (isVerticalFadingEdgeEnabled()) {
			setVerticalScrollBarEnabled(false);
		}
		for (int i = 0; i < pointerCount; i++) {
			if (currentHeaderStatus == HEADER_STATUS_DROP_DOWN_TO_LOAD
					|| currentHeaderStatus == HEADER_STATUS_RELEASE_TO_LOAD) {
				headerLayout
						.setPadding(
								headerLayout.getPaddingLeft(),
								(int)(((ev.getHistoricalY(i) - actionDownPointY) - headerOriginalHeight) / headerPaddingTopRate),
								headerLayout.getPaddingRight(), headerLayout.getPaddingBottom());
			}
		}
	}

	/**
	 * reset header padding
	 */
	private void resetHeaderPadding() {
		headerLayout.setPadding(headerLayout.getPaddingLeft(), headerOriginalTopPadding,
				headerLayout.getPaddingRight(), headerLayout.getPaddingBottom());
	}

	/**
	 * measure header layout
	 *
	 * @param child
	 */
	private void measureHeaderLayout(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
		}

		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
		}
		child.measure(childWidthSpec, childHeightSpec);
	}

	/**
	 * get attrs
	 *
	 * @param context
	 * @param attrs
	 */
	private void getAttrs(Context context, AttributeSet attrs) {
		TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.drop_down_list_attr);
		isDropDownStyle = ta.getBoolean(R.styleable.drop_down_list_attr_isDropDownStyle, false);
//		isOnBottomStyle = ta.getBoolean(R.styleable.drop_down_list_attr_isOnBottomStyle, false);
//		isAutoLoadOnBottom = ta.getBoolean(R.styleable.drop_down_list_attr_isAutoLoadOnBottom, false);
		ta.recycle();
	}
}
